也说谭浩强大师的低级错误
13 03 2009年张云楼同学说:
《C程序设计》例3.3说在TurboC上32767+1没有得到32768,得到的是-32768。然后作者说“将变量b改成long型就可以得到预期结果32768了”,敢问谭教授上机试过没有,我试过了,不行。
“注意版本”同学驳斥说:
例1作者试过了TC几个版本,编译模式估计是缺省的,改过吗?感觉现在用TC很少了吧,近20年前流行的。我相信教材作者至少在某个版本上试验过,很可能后来版本更新了引起问题。版本兼容性问题在计算机界普遍存在。
谭大师在《C程序设计》(2005年第三版第44页)说:
在Turbo C和Turbo C++中,一个int型的变量的最大允许值为32767,如果再加1,会出现什么情况?
例3.3 整型数据的溢出
#include <stdio.h>
main()
{
int a,b;
a=32767;
b=a+1;
printf(”%d, %d\n”, a, b);
}
运行结果为:
32767, -32768
……将变量b改成long型就可得到预期结果32768。
经Turbo C 2.01实验(其他16位编译系统应有同样结果),证明谭大师所说的“将变量b改成long型就可得到预期结果32768”错误。
将变量b改成long型,输出仍为-32768。原因是printf函数按%d两字节int型整数格式,取传递过来的b的4字节中的低两字节(二进制1000000000000000,对应-32768)输出。
再将printf中与b对应的格式符%d改为%ld,输出仍为-32768。原因是b=a+1一句中,a+1运算按编译器默认的两字节整数进行,结果为二进制1000000000000000(对应-32768);赋值给b时,b的高两字节将进行符号位扩展(而非填0),b的值为二进制11111111111111111000000000000000(对应4字节long型整数-32768)。因此,还必须将a+1中的a或1强制转换或设置为long型,使a+1运算按4字节整数进行,才能得到预期结果32768。
以下是修改后的程序(三处修改缺一不可):
#include <stdio.h>
main()
{
int a;
long b;
a=32767;
b=(long)a+1; /* or b=a+1L */
printf(”%d, %ld\n”, a, b);
}
谭大师所谓“将变量b改成long型就可得到预期结果32768”不可能在任何一个16位C编译系统上成功(而在32位系统上,根本不会出现例3.3的溢出问题),因此,谭大师显然如张云楼同学所猜测没有上机试过;也不存在“注意版本”同学所谓的“版本更新了引起问题”。
注:可在http://books.google.com中搜索“整型数据的溢出”,即可一瞻谭大师大作风采(封面上赫然印着“发行700万册记录”)。
补记:
在网上找了个谭浩强著《C程序设计》第二版扫描版(未知出版年份版次),错误与google books上的第三版(2005年清华大学出版社)相同。又据无敌法王提供的第二版(2004年9月第53次印刷),相应表述已改正为:“将变量a和b改成long型,并按%ld格式输出,就可得到预期的结果32768”。据此推测,此书第三版是在错误的第二版老版本上“升级”的,在这方面,确如“注意版本”同学所说,“版本更新了引起问题”。
补记2:
据无敌法王亲自前往新华书店核实,本书第三版第22次印刷中错误已纠正为:
“将变量b改成long型(同时将a+1改成a+1L,并按%ld格式输出),就可得到预期结果32768。”
谭大师所说的“将变量b改成long型就可得到预期结果32768”,只是一个原则,当然在关于b的运算上也需要修改成long型。他并没有说只要把第4行从int a,b变成int a; long b 就可得到预期结果32768。
重要的是,谭是在说道理,而且说得很正确,不知道你们到底在争什么。
回复Ben:重要的是,谭是在说那段具体的程序,而不仅仅是说原则、道理。原则、道理我一开始就认为说得没错:
http://www.xys.org/forum/db/4/179/61.html
送交者: Yush 于 2009-03-12, 14:09:50:
TurboC环境下,int为2字节。在此前提下,谭教授的表述没有错
我没有这本书,猜测可能是书上给的示例程序或张云楼自己写的程序的输出语句有问题。
“将变量b改成long型就可得到预期结果32768”这句话中的“就”字,表明谭将“将变量b改成long型”作为那段程序运行成功的充分条件。
我在网上也见到了此说引起的困惑(而且“高人指点迷津”也没有指点对):
http://zhidao.baidu.com/question/43149527.html
这个书上的例子,这样算的结果是3767,-32768 说是将变量b改成long型就可以得到预期结果32768.我该怎么做呢?是在哪里加上long?我试了几个地方都不行,望高人指点迷津!!
比如说,布什带领美国,把经济搞得很差,大家说:“让obama当总统就行了。”
这不仅意味着让obama宣誓当总统,还要让他有职权任命人事,制定政策。
如果谭大师说:“让obama当总统就行了,还是用以前的人事,还是用以前的政策。”这时我们再来抨击他吧。
让obama当总统,就表示让他有总统的权利来运作。同样,“将变量b改成long型”,也表示与b有关的运算也修改成long型,也就是你所给的修改后的程序(三处修改缺一不可)。原句“将变量b改成long型”并不是具体操作语句,而是一个方案。
据说有的《C程序设计》版本上的表述是:“将变量a和b改成long型,并按%ld格式输出,就可得到预期的结果32768”。BEN,那你该怎么用obama当总统类比这种表述?
当然了,谭大师既然是大师,高瞻远瞩指导一下“原则、道理”、提出一个“方案”就行了,当然不用管“具体操作语句”,用不着亲自运行调试示例程序。
如果谭浩强真的是那么说,当然是错的。没什么好争。这不是讲道理,他拿了个实例,实例错了就是错了。
可是我手头的书,谭浩强的说法却是正确。可网上的所谓“第二版”,那句话竟然是错的?我是书是新华书店买的,网上的扫描版倒有盗版的可能。
“将变量a和b改成long型,并按%ld格式输出,就可得到预期的结果32768” 只是对“将变量b改成long型”的深化,也许上一版本说得简略,有学生提出疑问,故此加深了一下,很正常。
每本书,每篇文字,并不是要对每句话都“亲自运行调试示例程序”的。如果需要的话,还要说清楚每句语句后面需要回车,然后选择菜单项编译,输出结果窗口如何阅读…比如说让obama当总统,不需要交代清楚给他发个门卡,进出白宫划卡进入,厕所在右侧,每天可以上4次,上厕所前请警卫检查安全…
言尽于此。没有什么好说的了。
Ben,你一说“言尽于此。没有什么好说的了”,让我想起了老朋友松鼠:)
法王,我搞不清楚这版本是怎么回事。
你提到,1999年第二版2004年9月第53次印刷是正确的:“将变量a和b改成long型,并按%ld格式输出,就可得到预期的结果32768”。
我是从google books上看到的:
http://books.google.com/books?id=EohQSpIjLy0C&printsec=frontcover&source=gbs_summary_r&cad=0
谭浩强著《C程序设计》(第三版)
2005年清华大学出版社
ISBN 7-302-10853-6
网上找了个第二版扫描版(不知出版年份版次),与google books上的错误相同:
http://www.eshuba.com/down.asp?id=7974&no=1
上述两个版本的不同是,如第三版封底所言,第三版中去掉了第二版中关于C++初步知识的第14章和第15章。
我用笔记本自带的摄相头拍了下来,不太清楚,不过可以依稀辨认。怎么发图?
发图:
http://xysblogs.org/faq#q7
yush: 我就是松鼠啊。你看我留了blog地址的。
是呀松鼠,我一想起了老朋友松鼠,就点了你的blog看了看:)
按部就班操作了,你能看到吗?我看不到。
能不能打包上传,让大家下载查看?
http://photo.blog.sina.com.cn/category/u/1250446424/s/10442
法王,你这照片上这页跟我网上找的那个第二版扫描版排版一样,只是那句话改正了。看来第三版是在错误的第二版老版本上“升级”的,“版本更新了引起问题”。
你丫的,书仔细看下,第二版P45,明明写着将变量a,b改成long 并按%ld格式输出@
Yush回应:你丫的看清楚没有?在本书第二版、第三版的不同印刷版次中,这部分内容多次改来改去。